package com.valenx.distributedmulticamerasystem.camera.recorder;

import com.valenx.distributedmulticamerasystem.camera.constant.RecorderStatus;
import ohos.agp.graphics.Surface;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.media.common.AudioProperty;
import ohos.media.common.Source;
import ohos.media.common.StorageProperty;
import ohos.media.common.VideoProperty;
import ohos.media.image.common.Size;
import ohos.media.recorder.Recorder;

import java.io.FileDescriptor;
import java.util.Optional;

//录像操作对象封装类
public class VideoRecorder {
    private Recorder recorder; //录像操作对象
    private EventHandler videoRecorderHandler;//事件控制器
    private RecorderStatus recordStatus = RecorderStatus.IDLE;//录像操作对象状态
    private VideoProperty.Builder videoPropertyBuilder;//视频配置器
    private AudioProperty.Builder audioPropertyBuilder;//音频配置器
    private StorageProperty.Builder storagePropertyBuilder;//存储配置器
//=============================================================================================================

    //构造器
    private VideoRecorder(Builder builder) {
        videoRecorderHandler = new EventHandler(EventRunner.create(VideoRecorder.class.getSimpleName()));
        videoPropertyBuilder = new VideoProperty.Builder();
        audioPropertyBuilder = new AudioProperty.Builder();
        storagePropertyBuilder = new StorageProperty.Builder();
        recorder = new Recorder();
        init(builder);
    }
//=============================================================================================================

    //Builder内部类
    public static class Builder {
        private FileDescriptor saveFd;//外部存储文件标识符
        private Size resolution;//分辨率
        private int degrees;//旋转角度
        private final int fps = 30;//采样帧率
        private final int frameRate = 30;//帧率
        private final int bitRate = 10000000;//比特率

        //构造器
        public Builder() {
        }

        //设置外部存储文件标识符
        public VideoRecorder.Builder setSaveFd(FileDescriptor saveFd) {
            this.saveFd = saveFd;
            return this;
        }

        //设置分辨率
        public VideoRecorder.Builder setResolution(Size resolution) {
            this.resolution = resolution;
            return this;
        }

        //设置旋转角度
        public VideoRecorder.Builder setDegrees(int degrees) {
            this.degrees = degrees;
            return this;
        }

        //创建VideoRecorder
        public VideoRecorder build() {
            return new VideoRecorder(this);
        }
    }
//************************************************************************************************************

    //初始化recorder
    private void init(Builder builder) {
        initVideoProperty(builder);
        initAudioProperty();
        initStorageProperty(builder);
        initRecorder();
    }
//************************************************************************************************************

    //初始化视频配置
    private void initVideoProperty(Builder builder) {
        videoPropertyBuilder.setRecorderDegrees(builder.degrees);
        videoPropertyBuilder.setRecorderFps(builder.fps);
        videoPropertyBuilder.setRecorderWidth(Math.max(builder.resolution.width, builder.resolution.height));
        videoPropertyBuilder.setRecorderHeight(Math.min(builder.resolution.width, builder.resolution.height));
        videoPropertyBuilder.setRecorderVideoEncoder(Recorder.VideoEncoder.H264);
        videoPropertyBuilder.setRecorderRate(builder.frameRate);
        videoPropertyBuilder.setRecorderBitRate(builder.bitRate);
    }
//************************************************************************************************************

    //初始化音频配置
    private void initAudioProperty() {
        audioPropertyBuilder.setRecorderAudioEncoder(Recorder.AudioEncoder.AAC);
    }
//************************************************************************************************************

    //初始化存储配置
    private void initStorageProperty(Builder builder) {
        storagePropertyBuilder.setRecorderFd(builder.saveFd);
    }
//************************************************************************************************************

    //初始化录像操作对象
    private void initRecorder() {
        Source source = new Source();
        source.setRecorderAudioSource(Recorder.AudioSource.MIC);
        source.setRecorderVideoSource(Recorder.VideoSource.SURFACE);
        recorder.setSource(source);
        recorder.setOutputFormat(Recorder.OutputFormat.MPEG_4);
        recorder.setVideoProperty(videoPropertyBuilder.build());
        recorder.setAudioProperty(audioPropertyBuilder.build());
        recorder.setStorageProperty(storagePropertyBuilder.build());
    }
//************************************************************************************************************

    //准备录像
    public void prepare() {
        if (recordStatus == RecorderStatus.IDLE) {
            if (recorder.prepare()) {
                recordStatus = RecorderStatus.PREPARED;
            }
        }
    }
//************************************************************************************************************

    //开始录像
    public void start() {
        if (recordStatus != RecorderStatus.IDLE && recordStatus != RecorderStatus.START) {
            videoRecorderHandler.postTask(() -> {
                if (recorder.start()) {
                    recordStatus = RecorderStatus.START;
                }
            });
        }
    }
//************************************************************************************************************

    //停止录像
    public void stop() {
        if (recordStatus != RecorderStatus.IDLE) {
            videoRecorderHandler.postTask(() -> {
                if (recorder.stop()) {
                    recordStatus = RecorderStatus.STOP;
                }
            });
        }
    }
//************************************************************************************************************

    //重置
    public void reset(Builder builder) {
        if (recorder.reset()) {
            recordStatus = RecorderStatus.IDLE;
        }
        init(builder);
        prepare();
    }
//************************************************************************************************************

    //释放录像操作对象
    public void release() {
        if (recorder.release()) {
            recordStatus = RecorderStatus.IDLE;
        }
    }
//************************************************************************************************************

    //获取录像状态
    public RecorderStatus getStatus() {
        return recordStatus;
    }
//************************************************************************************************************

    //获取录像画布
    public Optional<Surface> getRecordSurface() {
        if (recorder != null) {
            return Optional.of(recorder.getVideoSurface());
        }
        return Optional.empty();
    }
}
